package com.dongnam.quanly.common.model;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
@Table(name = "usergroup")
public class UserGroup implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@Column(name = "GROUPID", length = 30)
	private String groupId;
	@Column(name = "GROUPNAME", length = 60, unique = true)
	private String groupName;
	@Column(name = "CREATEDATE")
	private Timestamp createDate;
	@Version
	@Column(name = "LASTUPDATEDON")
	private Timestamp lastUpdatedOn;
	@Column(name = "LASTUPDATEDBY", length = 30)
	private String lastUpdatedBy;
	// NOTE: use ManyToMany will make us unable to implement locking on
	// JoinTable since we cannot add attribute on it
	@ManyToMany(targetEntity = UserRole.class)
	@JoinTable(name = "grouprole", joinColumns = @JoinColumn(name = "GROUPID"), inverseJoinColumns = @JoinColumn(name = "ROLEID"))
	@org.hibernate.annotations.ForeignKey(name = "FK_GROUPROLE_USERGROUP")
	@Cascade(value = { CascadeType.SAVE_UPDATE })
	private Set<UserRole> userRoles;

	// inverse side
	@OneToMany(mappedBy = "group", orphanRemoval = true)
	@Cascade(value = { CascadeType.SAVE_UPDATE, CascadeType.DELETE })
	private Set<ConsoleUser> consoleUsers;

	public UserGroup() {
		createDate = new Timestamp(System.currentTimeMillis());
	}

	public UserGroup(String groupId, String groupName, String lastUpdatedBy) {
		this.groupId = groupId;
		this.groupName = groupName;
		this.lastUpdatedBy = lastUpdatedBy;
		this.createDate = new Timestamp(System.currentTimeMillis());
	}

	public String getGroupId() {
		return groupId;
	}

	public void setGroupId(String groupId) {
		this.groupId = groupId;
	}

	public String getGroupName() {
		return groupName;
	}

	public void setGroupName(String groupName) {
		this.groupName = groupName;
	}

	public Timestamp getCreateDate() {
		return createDate;
	}

	public void setCreateDate(Timestamp createDate) {
		this.createDate = createDate;
	}

	public Timestamp getLastUpdatedOn() {
		return lastUpdatedOn;
	}

	public void setLastUpdatedOn(Timestamp lastUpdatedOn) {
		this.lastUpdatedOn = lastUpdatedOn;
	}

	public String getLastUpdatedBy() {
		return lastUpdatedBy;
	}

	public void setLastUpdatedBy(String lastUpdatedBy) {
		this.lastUpdatedBy = lastUpdatedBy;
	}

	// to be accessed by another pojo for "bi-directional link management"
	public Set<UserRole> getUserRoles() {
		return userRoles;
	}

	protected void setUserRoles(Set<UserRole> userRoles) {
		this.userRoles = userRoles;
	}

	protected Set<ConsoleUser> getConsoleUsers() {
		return consoleUsers;
	}

	protected void setConsoleUsers(Set<ConsoleUser> consoleUsers) {
		this.consoleUsers = consoleUsers;
	}

	public void addConsoleUser(ConsoleUser consoleUser) {
		System.out.println("addConsoleUser == null? " + consoleUsers == null);
		if (consoleUsers == null) {
			consoleUsers = new HashSet<ConsoleUser>();
		}
		consoleUsers.add(consoleUser);
		consoleUser.setGroup(this);
	}

	public void removeConsoleUser(ConsoleUser consoleUser) {
		if (consoleUsers != null) {
			consoleUsers.remove(consoleUser);
		}
		// consoleUser.setGroup(null); // do not expect group to be null, so do
		// not set, plz just do not use this ConsoleUser after remove
	}

	public void removeAllConsoleUser() {
		if (this.consoleUsers != null) {
			consoleUsers.clear();
		}
	}

	/**
	 * Warning: HAVE NOT ensured referential integrity. Do it manually as
	 * follow:
	 * <p>
	 * <code>
	 * userGroup.addUserRole(userRole);<br/>
	 * userRole.addUserGroup(userGroup);
	 * </code>
	 * </p>
	 */
	public void addUserRole(UserRole userRole) {
		if (userRoles == null) {
			userRoles = new HashSet<UserRole>();
		}
		userRoles.add(userRole);
	}

	/**
	 * Warning: HAVE NOT ensured referential integrity. Do it manually as
	 * follow:
	 * <p>
	 * <code>
	 * userGroup.removeUserRole(userRole);<br/>
	 * userRole.removeUserGroup(userGroup);
	 * </code>
	 * </p>
	 */
	public void removeUserRole(UserRole userRole) {
		if (userRoles == null) {
			userRoles = new HashSet<UserRole>();
		}
		userRoles.remove(userRole);
	}

	public void removeAllUserRoles() {
		if (userRoles == null) {
			userRoles = new HashSet<UserRole>();
		}
		userRoles.clear();
	}

	public String toString() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("groupId: " + groupId + ";");
		buffer.append("groupName: " + groupName + ";");
		if (createDate != null) {
			buffer.append("createDate: " + createDate.toString() + ";");
		}
		if (lastUpdatedOn != null) {
			buffer.append("lastUpdatedOn: " + lastUpdatedOn.toString() + ";");
		}
		if (lastUpdatedBy != null) {
			buffer.append("lastUpdatedBy: " + lastUpdatedBy);
		}
		return buffer.toString();
	}
}